#include "thread_pool.h"
#include "logger.h"
#include <boost/bind.hpp>

namespace mars {

ThreadPool::ThreadPool(): 
    _stop(true),
     _mutex(),
    _cond() {
}

ThreadPool::~ThreadPool() {
    DEBUG_PRINT("thread pool destroy\n");
    if (!_stop) {
        stop();
    }
    DEBUG_PRINT("%d tasks are not processed\n", _task_list.size());
}

void ThreadPool::start(int num) {
    assert(_stop);
    assert(_threads.empty());

    _stop = false;
    char thread_name[64];
    DEBUG_PRINT("thread pool start\n");
    for (int i = 0; i < num; ++i) {
        // _threads 是 ThreadPool 的成员，所以他们的生命周期长度是相同的
        // 为每个线程取个名字，方便追踪
        snprintf(thread_name, 64, "thread[%d]", i);
        _threads.push_back(new Thread(boost::bind(&ThreadPool::power, this), thread_name));
        _threads.back().start();
    }
}

void ThreadPool::run(const Task& task) {
    DEBUG_PRINT("new task insert task list\n");
    MutexLockGuard guard(_mutex);
    _task_list.push_back(task);
    _cond.notify();
}

void ThreadPool::stop() {
    DEBUG_PRINT("thread pool stop\n");
    _stop = true;
    // 唤醒所有被阻塞的线程
    _cond.notifyAll();
    for_each(_threads.begin(), _threads.end(), boost::bind(&Thread::join, _1));
}

ThreadPool::Task ThreadPool::get_task() {
    MutexLockGuard guard(_mutex);

    // 使用 while 防止虚假唤醒(spurious wakeup)
    while (_task_list.empty() && !_stop) {
        // 解锁并等待
        DEBUG_PRINT("%s wait for task list\n", CurrentThread::name());
        _cond.wait(_mutex);
    }

    DEBUG_PRINT("%s wakeup\n", CurrentThread::name());
    Task task;
    // 如果 pool 已经被停掉而导致上面的循环退出，还应该再判断一下任务队列是否为空
    if (!_task_list.empty()) {
        DEBUG_PRINT("%s pick task from task list\n", CurrentThread::name());
        task = _task_list.front();
        _task_list.pop_front();
    }
    return task;
}

void ThreadPool::power() {
    while(!_stop) {
        Task task = get_task();
        DEBUG_PRINT("%s power task\n", CurrentThread::name());
        if (!task.empty())
            task();
    }
}

} // namespace mars
